#include "ConfigManager.h"

#include <QCoreApplication>
#include <QDebug>
#include <QFileInfo>
#include <QStandardPaths>

// 初始化静态成员变量
ConfigManager* ConfigManager::m_instance = nullptr;

ConfigManager* ConfigManager::instance()
{
    if (!m_instance) {
        m_instance = new ConfigManager();
    }
    return m_instance;
}

ConfigManager::ConfigManager(QObject* parent) : QObject(parent), m_modified(false)
{
    // 默认配置目录为应用程序数据目录下的config子目录
    m_configDir = "./config";

    // 默认配置文件名
    m_configFilename = "app_config.json";

    // 确保配置目录存在
    ensureConfigDirExists();
}

ConfigManager::~ConfigManager()
{
    // 如果配置已修改，自动保存
    if (m_modified) {
        saveConfig();
    }
}

void ConfigManager::setConfigDir(const QString& path)
{
    m_configDir = path;
    ensureConfigDirExists();
}

void ConfigManager::setConfigFilename(const QString& filename) { m_configFilename = filename; }

QString ConfigManager::configDir() const { return m_configDir; }

QString ConfigManager::configFilePath() const { return m_configDir + "/" + m_configFilename; }

bool ConfigManager::ensureConfigDirExists() const
{
    QDir dir(m_configDir);
    if (!dir.exists()) {
        bool success = dir.mkpath(".");
        if (!success) {
            qWarning() << "Failed to create config directory:" << m_configDir;
        }
        return success;
    }
    return true;
}

bool ConfigManager::loadConfig()
{
    QString filePath = configFilePath();
    QFile file(filePath);

    // 如果文件不存在，返回false但不报错
    if (!file.exists()) {
        qDebug() << "Config file does not exist, will be created on save:" << filePath;
        m_rootConfig = QJsonObject();
        return false;
    }

    if (!file.open(QIODevice::ReadOnly)) {
        qWarning() << "Failed to open config file for reading:" << filePath;
        return false;
    }

    QByteArray data = file.readAll();
    file.close();

    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(data, &error);

    if (error.error != QJsonParseError::NoError) {
        qWarning() << "Failed to parse config file:" << filePath << "Error:" << error.errorString();
        return false;
    }

    if (!doc.isObject()) {
        qWarning() << "Config file is not a JSON object:" << filePath;
        return false;
    }

    m_rootConfig = doc.object();
    m_modified = false;

    return true;
}

bool ConfigManager::saveConfig()
{
    if (!ensureConfigDirExists()) {
        return false;
    }

    QString filePath = configFilePath();
    QFile file(filePath);

    if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
        qWarning() << "Failed to open config file for writing:" << filePath;
        return false;
    }

    QJsonDocument doc(m_rootConfig);
    file.write(doc.toJson(QJsonDocument::Indented));
    file.close();

    m_modified = false;
    qDebug() << "Successfully saved config to" << filePath;
    return true;
}

QJsonObject ConfigManager::getSection(const QString& section) const
{
    if (m_rootConfig.contains(section) && m_rootConfig[section].isObject()) {
        return m_rootConfig[section].toObject();
    }
    return QJsonObject();
}

void ConfigManager::setSection(const QString& section, const QJsonObject& data)
{
    m_rootConfig[section] = data;
    m_modified = true;
    emit configChanged(section);
}

QVariant ConfigManager::getValue(const QString& section, const QString& key,
                                 const QVariant& defaultValue) const
{
    if (!m_rootConfig.contains(section) || !m_rootConfig[section].isObject()) {
        return defaultValue;
    }

    QJsonObject sectionObj = m_rootConfig[section].toObject();
    if (!sectionObj.contains(key)) {
        return defaultValue;
    }

    QJsonValue value = sectionObj.value(key);

    switch (value.type()) {
        case QJsonValue::Bool:
            return value.toBool();
        case QJsonValue::Double:
            return value.toDouble();
        case QJsonValue::String:
            return value.toString();
        case QJsonValue::Array:
            return value.toArray();
        case QJsonValue::Object:
            return value.toObject();
        default:
            return defaultValue;
    }
}

void ConfigManager::setValue(const QString& section, const QString& key, const QVariant& value)
{
    QJsonObject sectionObj;

    // 如果配置节已存在，则获取它
    if (m_rootConfig.contains(section) && m_rootConfig[section].isObject()) {
        sectionObj = m_rootConfig[section].toObject();
    }

    // 根据值类型设置JSON值
    switch (value.type()) {
        case QVariant::Bool:
            sectionObj[key] = value.toBool();
            break;
        case QVariant::Int:
        case QVariant::Double:
            sectionObj[key] = value.toDouble();
            break;
        case QVariant::String:
            sectionObj[key] = value.toString();
            break;
        case QVariant::List:
        case QVariant::StringList:
            sectionObj[key] = QJsonArray::fromVariantList(value.toList());
            break;
        case QVariant::Map:
            sectionObj[key] = QJsonObject::fromVariantMap(value.toMap());
            break;
        default:
            if (value.canConvert<QString>()) {
                sectionObj[key] = value.toString();
            } else {
                qWarning() << "Unsupported variant type for config:" << value.typeName();
                return;
            }
    }

    // 更新配置节
    m_rootConfig[section] = sectionObj;
    m_modified = true;
    emit configChanged(section);
}

bool ConfigManager::hasSection(const QString& section) const
{
    return m_rootConfig.contains(section) && m_rootConfig[section].isObject();
}

bool ConfigManager::hasKey(const QString& section, const QString& key) const
{
    if (!hasSection(section)) {
        return false;
    }

    return m_rootConfig[section].toObject().contains(key);
}

void ConfigManager::removeSection(const QString& section)
{
    if (m_rootConfig.contains(section)) {
        m_rootConfig.remove(section);
        m_modified = true;
        emit configChanged(section);
    }
}

void ConfigManager::removeKey(const QString& section, const QString& key)
{
    if (hasKey(section, key)) {
        QJsonObject sectionObj = m_rootConfig[section].toObject();
        sectionObj.remove(key);
        m_rootConfig[section] = sectionObj;
        m_modified = true;
        emit configChanged(section);
    }
}

QStringList ConfigManager::getSections() const
{
    QStringList sections;
    for (auto it = m_rootConfig.begin(); it != m_rootConfig.end(); ++it) {
        if (it.value().isObject()) {
            sections.append(it.key());
        }
    }
    return sections;
}